package com.yjd.comm.fundservice.util;

import com.alibaba.fastjson.JSON;
import com.yjd.comm.cache.RedisCachUtils;
import com.yjd.comm.encrypt.AesUtil;
import com.yjd.comm.encrypt.EncryptTool;
import com.yjd.comm.encrypt.RsaUtil;
import com.yjd.comm.enums.CachNameSpaceEnum;
import com.yjd.comm.fundservice.dto.QKConfig;
import com.yjd.comm.fundservice.dto.QKResponse;
import com.yjd.comm.fundservice.enums.BusTypeEnum;
import com.yjd.comm.fundservice.model.FundServiceLogModel;
import com.yjd.comm.fundservice.service.IFundServiceLogService;
import com.yjd.comm.util.FrameUtil;
import com.yjd.comm.util.HttpsUtil;
import com.yjd.comm.util.ServiceHolder;
import com.yjd.comm.util.StringUtil;
import com.yjd.comm.vo.Constant;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by yjd-wap on 2018/1/21.
 */
public class QianKangServerUtil {

    private static Logger logger = Logger.getLogger(QianKangServerUtil.class);

    /**
     *  获取资金配置信息
     * @return
     * @throws Exception
     */
    private static QKConfig getQKFundConfig()throws Exception{
        return   RedisCachUtils.getCachObject(CachNameSpaceEnum.SYS_PARAM_INFO, Constant.SysParamKeyEnum.QK_FUND_CONFIG.getValue(),QKConfig.class);
    }


    public static IFundServiceLogService getFundServiceLogService() {
        return ServiceHolder.getLocalService(IFundServiceLogService.class, "fundServiceLogService");
    }

    public static <T extends Object> T sendMsg(Object obj,String bus_url,BusTypeEnum busTypeEnum,String bus_id, Class<T> cs)throws Exception {
        Long start_time = 0l;
        Long end_time = 0l;
        String ask_content = "";
        String return_msg = "";
        try {
            QKConfig qkConfig = getQKFundConfig();
            if (qkConfig == null || StringUtil.isEmpty(qkConfig.getAsk_url()) || StringUtil.isEmpty(qkConfig.getMy_private_key()) || StringUtil.isEmpty(qkConfig.getQk_public_key())) {
                FrameUtil.throwBaseException1("接口配置参数异常！");
            }
            if (obj == null) {
                FrameUtil.throwBaseException1("请求业务数据不能为空");
            }

            if (StringUtil.isEmpty(bus_url)) {
                FrameUtil.throwBaseException1("请求url不能为空");
            }

            String url = qkConfig.getAsk_url() + bus_url;
            ask_content = busDataHandle(StringUtil.objectToMap(obj), qkConfig.getQk_public_key());//发送请求数据
            start_time = System.currentTimeMillis();
            return_msg = HttpsUtil.requestPostForm(url, FrameUtil.newHashMap("app_msg", ask_content));
            end_time = System.currentTimeMillis();

            // 转换响应格式数据
            QKResponse response = StringUtil.getObject(return_msg, QKResponse.class);

            // 将响应数据的data信息转换为cs对象数据
            return QianKangServerUtil.parseResponse(response, cs);

        } catch (Exception e) {
            logger.error("资金服务异常：" + e);
            throw e;
        } finally {
            //记录资金服务请求日志
            insertLog(1, start_time, end_time, busTypeEnum, bus_id, ask_content, return_msg);
        }

    }

    private static void insertLog(Integer fund_channel, Long start_time, Long end_time, BusTypeEnum bus_type,String bus_id, String ask_content,
                                 String return_msg){
        try {
            getFundServiceLogService().insert(new FundServiceLogModel(fund_channel,start_time,end_time,bus_type,bus_id,ask_content,return_msg,FrameUtil.getTime()));
        }catch (Exception e){
            logger.error("资金服务插入日期服务异常："+e);
        }
    }

    /**
     *  数据加密
     * @param param
     * @param pub_key
     * @return
     * @throws Exception
     */
    private static  String busDataHandle(Map param,String pub_key)throws Exception{
        String v1 = EncryptTool.generateRandom32();
        String v2 = EncryptTool.generateRandom16();
        String v3 = AesUtil.sortMapByKey(param);//对数据进行排序
        String v4 = EncryptTool.HMACSHA256Encode("agent_secret", v3); //签名数据
        param.put("sign",v4);
        String v5 = JSON.toJSONString(param);//生成json格式数据
        String v6 = Base64.encodeBase64String(v5.getBytes());//base64加密
        String v7 = RsaUtil.encryptByRsaPub(v1,pub_key);//加密后秘钥
        Map request = new HashMap();
        request.put("data",v6);
        request.put("sc",Base64.encodeBase64String(v7.getBytes()));
        request.put("iv",v2);
        return  JSON.toJSONString(request);
    }

    /**
     * 解析返回结果
     * @param response 返回信息
     * @param cs 返回信息类型
     * @return
     * @throws Exception
     */
    public static <T extends Object> T parseResponse(QKResponse response, Class<T> cs)throws Exception{

        Assert.notNull(response, "返回信息为空");

        // 响应码，0：成功，其他为异常
        if(response.getCode() > 0){
            logger.error("贷款处理失败，原因：" + response.getMessage());
            return null;
        }

        T to = parseData(response.getData(), "sc", "private_key", cs);
        Assert.notNull(to, "返回数据为空");

        return to;
    }

    /**
     * 解析返回结果
     * @param msg 返回信息
     * @param cs 返回信息类型
     * @return
     * @throws Exception
     */
    public static <T extends Object> T parseResponse(String msg, Class<T> cs)throws Exception{
        return parseResponse(StringUtil.getObject(msg, QKResponse.class), cs);
    }

    /**
     *  解析数据
     * @param data
     * @param private_key
     * @return
     * @throws Exception
     */
    private static <T extends Object> T parseData(String data,String sc,String private_key,Class<T> cs)throws Exception{
        String v1 = RsaUtil.decryptByRsaPri(sc,private_key);//私钥解密
        String v2 =  new String(Base64.decodeBase64(data));
        Map paseMap = StringUtil.getObject(v2,Map.class);
        String v3 = paseMap.get("sign").toString();
        paseMap.remove("sign");
        String v4 = AesUtil.sortMapByKey(paseMap);//明文排序
        String v5 = AesUtil.encryptByECB(v4, v1);//加密明文

        if(!v3.equals(v5)){
            FrameUtil.throwBaseException1("接口响应的数据不合法");
        }
        paseMap.put("sign",v3);
      return   StringUtil.getObject(JSON.toJSONString(paseMap),cs);
    }
}
